import { SqlBuildResult, SqlExecuteResult, SqlExecutor, TableBuildResult, TableColumn, TimestampsOptions, SoftDeleteOptions } from './types';

/**
 * SQLite实际支持的存储类型枚举
 */
export enum DataType {
  INTEGER = 'INTEGER',
  REAL = 'REAL',
  TEXT = 'TEXT',
  BLOB = 'BLOB',
  NUMERIC = 'NUMERIC'
}

/**
 * 逻辑数据类型到SQLite存储类的映射
 */
export const TypeMapping = {
  BOOLEAN: DataType.INTEGER,  // 0或1
  DATE: DataType.TEXT,        // ISO日期字符串
  DATETIME: DataType.TEXT,    // ISO日期时间字符串
  TIMESTAMP: DataType.INTEGER // Unix时间戳
};

/**
 * 列定义接口
 */
export interface ColumnDefinition {
  /** 列名 */
  name: string;
  /** 数据类型 */
  type: DataType | string;
  /** 是否为主键 */
  primaryKey?: boolean;
  /** 是否为自增 */
  autoIncrement?: boolean;
  /** 是否不为空 */
  notNull?: boolean;
  /** 是否唯一 */
  unique?: boolean;
  /** 默认值 */
  defaultValue?: any;
  /** 检查约束 */
  check?: string;
  /** 外键引用 */
  references?: {
    /** 引用表名 */
    table: string;
    /** 引用列名 */
    column: string;
    /** 更新行为 */
    onUpdate?: 'CASCADE' | 'RESTRICT' | 'SET NULL' | 'SET DEFAULT' | 'NO ACTION';
    /** 删除行为 */
    onDelete?: 'CASCADE' | 'RESTRICT' | 'SET NULL' | 'SET DEFAULT' | 'NO ACTION';
  };
}

/**
 * 索引定义接口
 */
export interface IndexDefinition {
  /** 索引名称 */
  name: string;
  /** 列名数组 */
  columns: string[];
  /** 是否唯一 */
  unique?: boolean;
}

/**
 * 表定义接口，用于JSON配置
 */
export interface TableDefinition {
  /** 表名 */
  name: string;
  /** 列定义 */
  columns: ColumnDefinition[];
  /** 索引定义 */
  indices?: IndexDefinition[];
  /** 是否为临时表 */
  temporary?: boolean;
  /** 是否不存在则创建 */
  ifNotExists?: boolean;
  /** 表备注 */
  comment?: string;
}

/**
 * 索引定义
 */
interface TableIndex {
  name: string;
  columns: string[];
  unique: boolean;
}

/**
 * 表构建器
 * 用于构建建表SQL语句
 */
export class TableBuilder {
  /** 表名 */
  private tableName: string;
  /** 列定义数组 */
  private columns: TableColumn[] = [];
  /** 索引定义数组 */
  private indices: TableIndex[] = [];
  /** 是否是临时表 */
  private isTemporary: boolean = false;
  /** 是否不存在则创建 */
  private ifNotExists: boolean = false;
  /** 表备注 */
  private tableComment?: string;
  /** SQL执行器 */
  private executor?: SqlExecutor;

  /**
   * 构造函数
   * @param tableName 表名
   */
  constructor(tableName: string) {
    this.tableName = tableName;
  }

  /**
   * 设置SQL执行器
   * @param executor SQL执行器
   * @returns 当前表构建器实例
   */
  public setExecutor(executor: SqlExecutor): TableBuilder {
    this.executor = executor;
    return this;
  }

  /**
   * 获取SQL执行器
   * @returns SQL执行器实例
   */
  public getExecutor(): SqlExecutor | undefined {
    return this.executor;
  }

  /**
   * 设置为临时表
   * @returns 当前表构建器实例
   */
  public temporary(): TableBuilder {
    this.isTemporary = true;
    return this;
  }

  /**
   * 设置为如果不存在则创建
   * @returns 当前表构建器实例
   */
  public ifNotExist(): TableBuilder {
    this.ifNotExists = true;
    return this;
  }

  /**
   * 设置表备注
   * @param comment 表备注
   * @returns 当前表构建器实例
   */
  public comment(comment: string): TableBuilder {
    this.tableComment = comment;
    return this;
  }

  /**
   * 添加列定义
   * @param column 列定义
   * @returns 当前表构建器实例
   */
  public addColumn(column: TableColumn): TableBuilder {
    this.columns.push(column);
    return this;
  }

  /**
   * 添加整数列
   * @param name 列名
   * @param options 列选项
   * @returns 当前表构建器实例
   */
  public integer(name: string, options: Partial<TableColumn> = {}): TableBuilder {
    return this.addColumn({
      name,
      type: 'INTEGER',
      ...options
    });
  }

  /**
   * 添加主键列
   * @param name 列名
   * @param options 列选项
   * @returns 当前表构建器实例
   */
  public id(name: string = 'id', options: Partial<Omit<TableColumn, 'primaryKey'>> = {}): TableBuilder {
    return this.addColumn({
      name,
      type: 'INTEGER',
      primaryKey: true,
      autoIncrement: true,
      ...options
    });
  }

  /**
   * 添加文本列
   * @param name 列名
   * @param options 列选项
   * @returns 当前表构建器实例
   */
  public text(name: string, options: Partial<TableColumn> = {}): TableBuilder {
    return this.addColumn({
      name,
      type: 'TEXT',
      ...options
    });
  }

  /**
   * 添加实数列
   * @param name 列名
   * @param options 列选项
   * @returns 当前表构建器实例
   */
  public real(name: string, options: Partial<TableColumn> = {}): TableBuilder {
    return this.addColumn({
      name,
      type: 'REAL',
      ...options
    });
  }

  /**
   * 添加布尔列
   * @param name 列名
   * @param options 列选项
   * @returns 当前表构建器实例
   */
  public boolean(name: string, options: Partial<TableColumn> = {}): TableBuilder {
    return this.addColumn({
      name,
      type: 'INTEGER',
      ...options
    });
  }

  /**
   * 添加BLOB列
   * @param name 列名
   * @param options 列选项
   * @returns 当前表构建器实例
   */
  public blob(name: string, options: Partial<TableColumn> = {}): TableBuilder {
    return this.addColumn({
      name,
      type: 'BLOB',
      ...options
    });
  }

  /**
   * 添加时间戳列
   * @param options 时间戳选项
   * @returns this
   */
  public timestamps(options: TimestampsOptions = {}): TableBuilder {
    const {
      createdAt = 'created_at',
      updatedAt = 'updated_at',
      useMilliseconds = false,
      notNull = true
    } = options;
    
    if (useMilliseconds) {
      // 使用毫秒级时间戳
      // 注意：在SQLite中，表定义的DEFAULT不能使用复杂表达式
      // 我们将使用触发器来实现此功能，这里先不设置默认值
      this.addColumn({
        name: createdAt,
        type: 'INTEGER',
        notNull
      });
      
      this.addColumn({
        name: updatedAt,
        type: 'INTEGER',
        notNull
      });
    } else {
      // 使用标准时间戳
      this.addColumn({
        name: createdAt,
        type: 'TEXT',
        notNull,
        defaultValue: 'CURRENT_TIMESTAMP'
      });
      
      this.addColumn({
        name: updatedAt,
        type: 'TEXT',
        notNull,
        defaultValue: 'CURRENT_TIMESTAMP'
      });
    }
    
    return this;
  }

  /**
   * 添加软删除列
   * @param options 软删除选项
   * @returns this
   */
  public softDeletes(options: SoftDeleteOptions = {}): TableBuilder {
    const {
      deletedAt = 'deleted_at',
      useMilliseconds = false,
      notNull = false
    } = options;
    
    this.addColumn({
      name: deletedAt,
      type: useMilliseconds ? 'INTEGER' : 'TEXT',
      notNull
    });
    
    return this;
  }

  /**
   * 添加索引
   * @param columns 索引列
   * @param options 索引选项
   * @returns 当前表构建器实例
   */
  public index(columns: string | string[], options: { name?: string, unique?: boolean } = {}): TableBuilder {
    const columnsArray = Array.isArray(columns) ? columns : [columns];
    const name = options.name || `${this.tableName}_${columnsArray.join('_')}_idx`;
    
    this.indices.push({
      name,
      columns: columnsArray,
      unique: options.unique || false
    });
    
    return this;
  }

  /**
   * 添加唯一索引
   * @param columns 索引列
   * @param options 索引选项
   * @returns 当前表构建器实例
   */
  public unique(columns: string | string[], options: { name?: string } = {}): TableBuilder {
    return this.index(columns, { ...options, unique: true });
  }

  /**
   * 构建SQL语句
   * @returns 表构建结果
   */
  public build(): TableBuildResult {
    const params: Record<string, any> = {};
    let sql = '';

    // 创建表
    sql += this.isTemporary ? 'CREATE TEMPORARY TABLE ' : 'CREATE TABLE ';
    
    // 如果不存在则创建
    if (this.ifNotExists) {
      sql += 'IF NOT EXISTS ';
    }

    // 表名
    sql += `${this.tableName} (\n`;

    // 列定义
    const columnDefs = this.columns.map(column => {
      let def = `  ${column.name} ${column.type}`;
      
      // 主键
      if (column.primaryKey) {
        def += ' PRIMARY KEY';
        
        // 自增
        if (column.autoIncrement) {
          def += ' AUTOINCREMENT';
        }
      }
      
      // 非空
      if (column.notNull) {
        def += ' NOT NULL';
      }
      
      // 唯一
      if (column.unique) {
        def += ' UNIQUE';
      }
      
      // 默认值
      if (column.defaultValue !== undefined) {
        if (typeof column.defaultValue === 'string') {
          // 判断是否是SQL表达式（含有特殊函数或操作符）
          if (column.defaultValue.includes('CURRENT_TIMESTAMP') || 
              column.defaultValue.includes('strftime') ||
              column.defaultValue.includes('datetime') ||
              column.defaultValue.includes('date') ||
              column.defaultValue.includes('time') ||
              column.defaultValue.includes('(') ||
              column.defaultValue.includes('+') ||
              column.defaultValue.includes('-') ||
              column.defaultValue.includes('*') ||
              column.defaultValue.includes('/')) {
            // SQL表达式不加引号
            def += ` DEFAULT ${column.defaultValue}`;
          } else {
            // 普通字符串加引号
            def += ` DEFAULT '${column.defaultValue}'`;
          }
        } else if (column.defaultValue === null) {
          def += ' DEFAULT NULL';
        } else if (typeof column.defaultValue === 'boolean') {
          def += ` DEFAULT ${column.defaultValue ? 1 : 0}`;
        } else if (typeof column.defaultValue === 'number') {
          def += ` DEFAULT ${column.defaultValue}`;
        } else {
          def += ` DEFAULT '${column.defaultValue}'`;
        }
      }
      
      // 检查约束
      if (column.check) {
        def += ` CHECK (${column.check})`;
      }
      
      // 外键引用
      if (column.references) {
        def += ` REFERENCES ${column.references.table}(${column.references.column})`;
        
        // 更新行为
        if (column.references.onUpdate) {
          def += ` ON UPDATE ${column.references.onUpdate}`;
        }
        
        // 删除行为
        if (column.references.onDelete) {
          def += ` ON DELETE ${column.references.onDelete}`;
        }
      }
      
      return def;
    });
    
    sql += columnDefs.join(',\n');
    sql += '\n)';
    
    // 表备注
    if (this.tableComment) {
      // SQLite不直接支持表注释，这里只是示意
      // 实际应用中，可能需要将注释存储在其他地方
      // 例如SQLite的sqlite_master或自定义的元数据表中
    }
    
    // 构建创建索引的SQL语句
    const indexSqls = this.indices.map(index => {
      const uniqueStr = index.unique ? 'UNIQUE ' : '';
      return `CREATE ${uniqueStr}INDEX IF NOT EXISTS ${index.name} ON ${this.tableName} (${index.columns.join(', ')})`;
    });

    return {
      sql,
      params,
      indexSqls
    };
  }

  /**
   * 执行SQL创建表
   * @param executor 可选的SQL执行器，如果未提供则使用内部设置的执行器
   * @returns 执行结果
   */
  public execute(executor?: SqlExecutor): SqlExecuteResult {
    const result = this.build() as SqlBuildResult & { indexSqls: string[] };
    const actualExecutor = executor || this.executor;
    
    if (!actualExecutor) {
      throw new Error('No SQL executor available. Please set an executor using setExecutor() or provide one as parameter.');
    }
    
    // 执行创建表语句
    const tableResult = actualExecutor.execute(result.sql, result.params);
    
    // 执行创建索引语句
    for (const indexSql of result.indexSqls) {
      actualExecutor.execute(indexSql, {});
    }
    
    return tableResult;
  }

  /**
   * 创建表构建器实例
   * @param tableName 表名
   * @returns 表构建器实例
   */
  public static create(tableName: string): TableBuilder {
    return new TableBuilder(tableName);
  }

  /**
   * 从JSON配置创建表
   * @param definition 表定义
   * @returns 表构建器实例
   */
  public static fromJSON(definition: TableDefinition): TableBuilder {
    const builder = new TableBuilder(definition.name);
    
    // 设置表选项
    if (definition.temporary) {
      builder.temporary();
    }
    
    if (definition.ifNotExists) {
      builder.ifNotExist();
    }
    
    if (definition.comment) {
      builder.comment(definition.comment);
    }
    
    // 添加列
    for (const column of definition.columns) {
      builder.addColumn(column);
    }
    
    // 添加索引
    if (definition.indices) {
      for (const index of definition.indices) {
        builder.index(index.columns, { name: index.name, unique: index.unique });
      }
    }
    
    return builder;
  }

  /**
   * 从JSON字符串创建表
   * @param jsonString JSON字符串
   * @returns 表构建器实例
   */
  public static fromJSONString(jsonString: string): TableBuilder {
    const definition = JSON.parse(jsonString) as TableDefinition;
    return TableBuilder.fromJSON(definition);
  }
} 